package com.emagic.manage.utils;

import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Handler;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 录音工具类
 */
public final class VoiceHelper {
    public static VoiceHelper sVoiceHelper;
    private boolean recording = false;
    private boolean playing = false;
    public RecordTimer mRecordTimer;
    private MediaRecorder mRecorder = null;
    public File mFileRecord;
    public MediaPlayer mPlayer;
    private Context ct;
    private VoiceRecordCallback callback;
    private VoicePlayCallback playCallback;

    private VoiceHelper(Context ct) {
        this.ct = ct;
    }

    public static VoiceHelper getInstance(Context ct) {
        if (sVoiceHelper == null) {
            sVoiceHelper = new VoiceHelper(ct);
        }
        return sVoiceHelper;
    }

    public void setRecordCallback(VoiceRecordCallback callback) {
        this.callback = callback;
    }

    public void setPlayCallback(VoicePlayCallback callback) {
        this.playCallback = callback;
    }

    public boolean isRecording() {
        return recording;
    }

    public boolean isPlaying() {
        return playing;
    }

    public class RecordTimer implements Runnable {
        private int mInterval = 100;
        private int mSec = 0;
        private Handler handler;

        public RecordTimer() {
            handler = new Handler();
        }

        @Override
        public void run() {
            mSec += mInterval;
            handler.postDelayed(this, mInterval);
        }

        public void reset() {
            mSec = 0;
        }

        public int getTime() {
            return mSec;
        }

        public void stop() {
            handler.removeCallbacks(this);
        }
    }

    public void startRecord() {
        recording = true;

        if (mRecorder != null) {
            return;
        }

        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

        String path = ct.getCacheDir().getPath();
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String RECORD_TEMP_FILE = "record_temp_file.mp4";
        mFileRecord = new File(path, "/" + RECORD_TEMP_FILE);
        mRecorder.setOutputFile(mFileRecord.getAbsolutePath());

        try {
            mRecorder.prepare();
            mRecorder.start();

            mRecordTimer = new RecordTimer();
            mRecordTimer.run();
        } catch (IllegalStateException | IOException e) {
            e.printStackTrace();
        }
    }

    public void stopRecord() {
        recording = false;
        mRecordTimer.stop();

        if (mRecorder != null) {
            try {
                mRecorder.stop();
            } catch (RuntimeException e) {
                e.printStackTrace();

                mRecorder.release();
                mRecorder = null;
                if (callback != null) {
                    callback.onFailed();
                }
            }

            if (mRecorder != null) {
                mRecorder.release();
                mRecorder = null;
            }
            if (callback != null) {
                callback.onSuccess(mFileRecord, mRecordTimer.getTime() / 1000.0);
            }
        } else {
            if (callback != null) {
                callback.onFailed();
            }
        }
    }

    public void cancelRecord() {
        recording = false;
        mRecordTimer.stop();

        if (mRecorder != null) {
            try {
                mRecorder.stop();
                mRecorder.release();
                mRecorder = null;
            } catch (RuntimeException e) {
                e.printStackTrace();

                mRecorder.release();
                mRecorder = null;
            }
        }
        if (callback != null) {
            callback.onCancel();
        }
    }

    public void playVoice(byte[] data) {
        try {
            // create temp file that will hold byte array
            File tempFile = File.createTempFile("temp", "mp4", ct.getCacheDir());
            tempFile.deleteOnExit();
            FileOutputStream fos = new FileOutputStream(tempFile);
            fos.write(data);
            fos.close();

            playVoice(tempFile);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void playVoice(File mediaFile) {
        try {
            if (mPlayer != null) {
                mPlayer.stop();
                mPlayer.release();
                mPlayer = null;
            }
            mPlayer = new MediaPlayer();
            mPlayer.setOnCompletionListener(mp -> {
                if (mPlayer != null) {
                    mPlayer.stop();
                    mPlayer.release();
                    mPlayer = null;
                    playing = false;
                    if (playCallback != null) {
                        playCallback.stop();
                    }
                }
            });
            if (mediaFile != null) {
                mPlayer.setDataSource(mediaFile.getAbsolutePath());
                mPlayer.prepare();
                mPlayer.start();
                playing = true;
                if (playCallback != null) {
                    playCallback.start();
                }
            }
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | IOException e) {
            e.printStackTrace();
        }
    }

    public interface VoicePlayCallback {
        void start();

        void stop();
    }

    public interface VoiceRecordCallback {
        void onCancel();

        void onFailed();

        void onSuccess(File file, double time);
    }
}
